package com.columboid.protocol.syncml.helper;

import java.io.StringReader;
import java.io.StringWriter;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import com.columboid.protocol.syncml.metainfo.Format;
import com.columboid.protocol.syncml.metainfo.MetInf;
import com.columboid.protocol.syncml.metainfo.NextNonce;
import com.columboid.protocol.syncml.metainfo.Type;
import com.columboid.protocol.syncml.representation.Chal;
import com.columboid.protocol.syncml.representation.Cred;
import com.columboid.protocol.syncml.representation.Final;
import com.columboid.protocol.syncml.representation.Source;
import com.columboid.protocol.syncml.representation.Status;
import com.columboid.protocol.syncml.representation.SyncBody;
import com.columboid.protocol.syncml.representation.SyncHdr;
import com.columboid.protocol.syncml.representation.SyncML;
import com.columboid.protocol.syncml.representation.Target;

public class JaxbHelper {
	

	public static <T> T CreateSyncMLObject(StringReader xmlReader,
			StringReader xsdReader,Class<T> instance,Class<?> factory) throws JAXBException, SAXException {
		JAXBContext jaxbContext = JAXBContext
				.newInstance(new Class[] { factory });

		SchemaFactory sf = SchemaFactory
				.newInstance(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI);

		Schema schema = sf.newSchema(new SAXSource(new InputSource(xsdReader)));

		Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
		unmarshaller.setSchema(schema);

		StreamSource source = new StreamSource(xmlReader);
		JAXBElement<T> smlElement =   unmarshaller
				.unmarshal(source, instance);
		T sml =   smlElement.getValue();
		return sml;
	}
	
	public static String getJaxbObjectString(SyncML sml,Boolean isFinal) throws JAXBException {
		if(isFinal)
		{
			Final finalNode = new Final();
			
			sml.getSyncBody().setFinal(finalNode);
		}
		
		return getJaxbObjectString(sml,SyncML.class,true);
	}
	
	public static <T> String getJaxbObjectString(T sml, Class<T> instance,Boolean declaration) throws JAXBException {
		StringWriter writer = new StringWriter();
		JAXBContext context = JAXBContext.newInstance(instance);
		
		Marshaller m = context.createMarshaller();
		m.marshal(sml, writer);
		
		String actual = writer.toString();
		if(!declaration)
		{
			String declarationString="<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>";
			actual=actual.substring(declarationString.length());
			
		}
		return actual;
	}
	
	
	public static SyncML getServerResponse(int sessionId,int msgId,String data,String nonce,String clientUri,String serverUri,String statusCode) throws JAXBException {
		SyncML sml = new SyncML();
		SyncHdr header = new SyncHdr();
		header.setVerDTD("1.1");
		header.setVerProto("SyncML/1.1");
		
		header.setSessionID(String.valueOf(sessionId));
		header.setMsgID(String.valueOf(msgId));

		Target target = new Target();
		target.setLocURI(clientUri);
	
		header.setTarget(target);

		Source source = new Source();
		source.setLocURI(serverUri);
	
		header.setSource(source);

		if(data!=null && data.length()>0)
		{
			Cred cred= new Cred();
			cred.setData(data);
			header.setCred(cred);
		}
		
		sml.setSyncHdr(header);
		SyncBody body = new SyncBody();
		Status status = new Status();
		status.setCmdID(String.valueOf(msgId));
		status.setCmdRef("0");
		status.setMsgRef(String.valueOf(msgId));
		status.setCmd("SyncHdr");
		status.getTargetRef().add(serverUri);
		status.getSourceRef().add(clientUri);
		//source.setLocURI(serverUri);
		

		Chal chal = new Chal();
		MetInf meta = new MetInf();
		Format format= new Format();
		format.setContent("b64");
		meta.setFormat(format);
		
		Type type= new Type();
		type.setContent("syncml:auth-md5");
		meta.setType(type);
		
		NextNonce nextNonce= new NextNonce();
		nextNonce.setContent(nonce);
		meta.setNextNonce(nextNonce);
		
		String metaString=JaxbHelper.getJaxbObjectString(meta, MetInf.class,false);
		
		
		
		/*String xml = "";

		xml += "<Type xmlns=\"syncml:metinf\">syncml:auth-md5</Type>";
		xml += "<Format xmlns=\"syncml:metinf\">b64</Format>";
		xml += "<NextNonce xmlns=\"syncml:metinf\">";
		xml += nonce;
		xml += "</NextNonce>";*/

		chal.setMeta(metaString);
		
		status.setChal(chal);
		status.setData(statusCode);

		body.getKeyOrRoutingOrAlert().add(status);
		

		sml.setSyncBody(body);

		return sml;
	}

	
	public static String getSyncMLSchema() {
		String xsd = "";
		xsd += "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
		xsd += "<!-- SyncML Representation Protocol DTD Version 1.1   2002-02-15 -->";
		xsd += "<!-- Root Element -->";
		xsd += "<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema' xmlns=\"http://protocol.columboid.com/syncml/representation\" elementFormDefault=\"qualified\" targetNamespace=\"http://protocol.columboid.com/syncml/representation\">";
		xsd += "  <xs:element name=\"SyncML\">";
		xsd += "		<xs:complexType>";
		xsd += "      <xs:sequence>";
		xsd += "        <xs:element ref=\"SyncHdr\"/>";
		xsd += "        <xs:element ref=\"SyncBody\"/>";
		xsd += "		 </xs:sequence>";
		xsd += "	    </xs:complexType>";
		xsd += "  </xs:element>";
		xsd += "<xs:element name=\"SyncHdr\">";
		xsd += "    <xs:complexType>";
		xsd += "		<xs:sequence>";
		xsd += "			<xs:element ref=\"VerDTD\"/>";
		xsd += "			<xs:element ref=\"VerProto\"/>";
		xsd += "			<xs:element ref=\"SessionID\"/>";
		xsd += "			<xs:element ref=\"MsgID\"/>";
		xsd += "			<xs:element ref=\"Target\"/>";
		xsd += "			<xs:element ref=\"Source\"/>";
		xsd += "			<xs:element minOccurs=\"0\" ref=\"RespURI\"/>";
		xsd += "			<xs:element minOccurs=\"0\" ref=\"NoResp\"/>";
		xsd += "			<xs:element minOccurs=\"0\" ref=\"Cred\"/>";
		xsd += "			<xs:element minOccurs=\"0\" ref=\"Meta\"/>";
		xsd += "		</xs:sequence>";
		xsd += "	</xs:complexType>";
		xsd += "</xs:element>";

		xsd += "<xs:element name=\"SyncBody\">";
		xsd += "<xs:complexType>";
		xsd += "  <xs:sequence>";
		xsd += "    <xs:choice maxOccurs=\"unbounded\">";
		xsd += "       <xs:element ref=\"Key\"/>";
		xsd += "       <xs:element ref=\"Routing\"/>";
		xsd += "       <xs:element ref=\"Alert\"/>";
		xsd += "       <xs:element ref=\"Atomic\"/>";
		xsd += "       <xs:element ref=\"Copy\"/>";
		xsd += "       <xs:element ref=\"Exec\"/>";
		xsd += "       <xs:element ref=\"Get\"/>";
		xsd += "      <xs:element ref=\"Map\"/>";
		xsd += "      <xs:element ref=\"Put\"/>";
		xsd += "     <xs:element ref=\"Results\"/>";
		xsd += "    <xs:element ref=\"Search\"/>";
		xsd += "   <xs:element ref=\"Sequence\"/>";
		xsd += "   <xs:element ref=\"Status\"/>";
		xsd += "  <xs:element ref=\"Sync\"/>";
		xsd += "  <xs:element ref=\"Add\"/>";
		xsd += " <xs:element ref=\"Replace\"/>";
		xsd += "  <xs:element ref=\"Delete\"/>";
		xsd += " </xs:choice>";
		xsd += " <xs:element minOccurs=\"0\" ref=\"Final\"/>";
		xsd += "</xs:sequence>";
		xsd += "</xs:complexType>";
		xsd += " </xs:element>";

		xsd += "<!-- Commonly Used Elements -->";
		xsd += "<!-- Archive indicator for Delete -->";
		xsd += " <xs:element name=\"Archive\">";
		xsd += " <xs:complexType/>";
		xsd += " </xs:element>";
		xsd += " <!-- Value must be one of \"Add\" | \"Alert\" | \"Atomic\" | \"Copy\" | \"Delete\" | \"Exec\" | \"Get\" | \"Map\" | \"Put\" | \"Replace\" | \"Results\" | \"Search\" | \"Sequence\" | \"Status\" | \"Sync\". -->";
		xsd += " <xs:element name=\"Cmd\" type=\"xs:string\"/>";
		xsd += " <!-- Authentication Challenge -->";
		xsd += "<xs:element name=\"Chal\">";
		xsd += "<xs:complexType>";
		xsd += "  <xs:sequence>";
		xsd += "    <xs:element ref=\"Meta\"/>";
		xsd += "		      </xs:sequence>";
		xsd += "		    </xs:complexType>";
		xsd += "		  </xs:element>";
		xsd += "		  <!-- Sync message unique identifier for command -->";
		xsd += "		  <xs:element name=\"CmdID\" type=\"xs:string\"/>";
		xsd += "		  <!-- Reference to command identifier -->";
		xsd += "		  <xs:element name=\"CmdRef\" type=\"xs:string\"/>";
		xsd += "		  <!-- Credentials -->";
		xsd += "		  <xs:element name=\"Cred\">";
		xsd += "	    <xs:complexType>";
		xsd += "	      <xs:sequence>";
		xsd += "        <xs:element minOccurs=\"0\" ref=\"Meta\"/>";
		xsd += "        <xs:element ref=\"Data\"/>";
		xsd += "      </xs:sequence>";
		xsd += "  </xs:complexType>";
		xsd += "			  </xs:element>";
		xsd += "		  <!-- Final message flag -->";
		xsd += "			  <xs:element name=\"Final\">";
		xsd += "		    <xs:complexType/>";
		xsd += "		  </xs:element>";
		xsd += "<!-- Desired language for results -->";
		xsd += "							  <xs:element name=\"Lang\" type=\"xs:string\"/>";
		xsd += "							  <!-- Location displayable name -->";
		xsd += "							  <xs:element name=\"LocName\" type=\"xs:string\"/>";
		xsd += "							  <!-- Location URI -->";
		xsd += "							  <xs:element name=\"LocURI\" type=\"xs:string\"/>";
		xsd += "<!-- Indication for more data to come -->";
		xsd += "<xs:element name=\"MoreData\">";
		xsd += "<xs:complexType/>";
		xsd += "</xs:element>";
		xsd += "<!-- SyncML Message ID -->";
		xsd += "<xs:element name=\"MsgID\" type=\"xs:string\"/>";
		xsd += "<!-- Reference to a SyncML Message ID -->";
		xsd += "<xs:element name=\"MsgRef\" type=\"xs:string\"/>";
		xsd += "<!-- No Response Status Requested Indicator -->";
		xsd += "<xs:element name=\"NoResp\">";
		xsd += "<xs:complexType/>";
		xsd += "</xs:element>";
		xsd += "<!-- No Results Requested Indicator -->";
		xsd += "<xs:element name=\"NoResults\">";
		xsd += "<xs:complexType/>";
		xsd += "</xs:element>";
		xsd += "<!-- NumberOfChanges used to display progress information -->";
		xsd += "<xs:element name=\"NumberOfChanges\" type=\"xs:string\"/>";
		xsd += "<!-- URI recipient used for response -->";
		xsd += "<xs:element name=\"RespURI\" type=\"xs:string\"/>";
		xsd += "<!-- SyncML session identifier -->";
		xsd += "<xs:element name=\"SessionID\" type=\"xs:string\"/>";
		xsd += "<!-- Soft delete indicator for Delete -->";
		xsd += "<xs:element name=\"SftDel\">";
		xsd += "<xs:complexType/>";
		xsd += "</xs:element>";
		xsd += "<!-- Source location -->";
		xsd += "<xs:element name=\"Source\">";
		xsd += "<xs:complexType>";
		xsd += "<xs:sequence>";
		xsd += "<xs:element ref=\"LocURI\"/>";
		xsd += "<xs:element minOccurs=\"0\" ref=\"LocName\"/>";
		xsd += "</xs:sequence>";
		xsd += "</xs:complexType>";
		xsd += "</xs:element>";
		xsd += "<xs:element name=\"SourceRef\" type=\"xs:string\"/>";
		xsd += "<!-- Target location information -->";
		xsd += "<xs:element name=\"Target\">";
		xsd += "<xs:complexType>";
		xsd += "<xs:sequence>";
		xsd += "<xs:element ref=\"LocURI\"/>";
		xsd += "<xs:element minOccurs=\"0\" ref=\"LocName\"/>";
		xsd += "</xs:sequence>";
		xsd += "</xs:complexType>";
		xsd += "</xs:element>";
		xsd += "<xs:element name=\"TargetRef\" type=\"xs:string\"/>";
		xsd += "<!-- SyncML specificaiton major/minor version info. -->";
		xsd += "<!-- For this version of the DTD, the value is \"1.1\" -->";
		xsd += "<xs:element name=\"VerDTD\" type=\"xs:string\"/>";
		xsd += "<!-- Data sync protocol major/minor version -->";
		xsd += "<!-- For example, \"xyz/1.1\" -->";
		xsd += "<xs:element name=\"VerProto\" type=\"xs:string\"/>";
		xsd += "<!-- Synchronization data elements -->";
		xsd += "<!-- Item element type -->";
		xsd += "<xs:element name=\"Item\">";
		xsd += "							    <xs:complexType>";
		xsd += "<xs:sequence>";
		xsd += "<xs:element minOccurs=\"0\" ref=\"Target\"/>";
		xsd += "<xs:element minOccurs=\"0\" ref=\"Source\"/>";
		xsd += "<xs:element minOccurs=\"0\" ref=\"Meta\"/>";
		xsd += "<xs:element minOccurs=\"0\" ref=\"Data\"/>";
		xsd += "<xs:element minOccurs=\"0\" ref=\"MoreData\"/>";
		xsd += "</xs:sequence>";
		xsd += "</xs:complexType>";
		xsd += "</xs:element>";
		xsd += "<!-- Meta element type -->";
		xsd += "<!-- Element types in the content MUST have name space declared. -->";
		xsd += "<!-- The Meta content would be something such as: <Meta> <Type xmlns='syncml:metinf'>text/calendar</Type> <Format xmlns='syncml:metinf'>xml</Format> </Meta> -->";
		xsd += "<xs:element name=\"Meta\" type=\"xs:string\"/>";
		xsd += "<!-- Actual data content -->";
		xsd += "<xs:element name=\"Data\" type=\"xs:string\"/>";
		xsd += "<!-- SyncML Commands -->";
		xsd += "<!-- Add operation. -->";
		xsd += "<xs:element name=\"Add\">";
		xsd += "<xs:complexType>";
		xsd += "<xs:sequence>";
		xsd += "<xs:element ref=\"CmdID\"/>";
		xsd += "<xs:element minOccurs=\"0\" ref=\"NoResp\"/>";
		xsd += "<xs:element minOccurs=\"0\" ref=\"Cred\"/>";
		xsd += "<xs:element minOccurs=\"0\" ref=\"Meta\"/>";
		xsd += "<xs:element maxOccurs=\"unbounded\" ref=\"Item\"/>";
		xsd += "</xs:sequence>";
		xsd += "</xs:complexType>";
		xsd += "</xs:element>";
		xsd += " <!-- Alert operation. -->";
		xsd += "<!-- Alert types are either \"User Agent\" or \"Application\" oriented -->";
		xsd += "<xs:element name=\"Alert\">";
		xsd += "<xs:complexType>";
		xsd += "<xs:sequence>";
		xsd += "<xs:element ref=\"CmdID\"/>";
		xsd += "<xs:element minOccurs=\"0\" ref=\"NoResp\"/>";
		xsd += "<xs:element minOccurs=\"0\" ref=\"Cred\"/>";
		xsd += "<xs:element minOccurs=\"0\" ref=\"Data\"/>";
		xsd += "<xs:element minOccurs=\"0\" maxOccurs=\"unbounded\" ref=\"Item\"/>";
		xsd += "</xs:sequence>";
		xsd += "</xs:complexType>";
		xsd += "</xs:element>";
		xsd += "<!-- Atomic operation. All or nothing semantics. -->";
		xsd += "<xs:element name=\"Atomic\">";
		xsd += "<xs:complexType>";
		xsd += "<xs:sequence>";
		xsd += "<xs:element ref=\"CmdID\"/>";
		xsd += "<xs:element minOccurs=\"0\" ref=\"NoResp\"/>";
		xsd += "							        <xs:element minOccurs=\"0\" ref=\"Meta\"/>";
		xsd += "<xs:choice maxOccurs=\"unbounded\">";
		xsd += "<xs:element ref=\"Add\"/>";
		xsd += "<xs:element ref=\"Replace\"/>";
		xsd += "<xs:element ref=\"Delete\"/>";
		xsd += "<xs:element ref=\"Copy\"/>";
		xsd += "<xs:element ref=\"Atomic\"/>";
		xsd += "<xs:element ref=\"Map\"/>";
		xsd += "<xs:element ref=\"Sequence\"/>";
		xsd += "<xs:element ref=\"Sync\"/>";
		xsd += "<xs:element ref=\"Get\"/>";
		xsd += "<xs:element ref=\"Exec\"/>";
		xsd += "<xs:element ref=\"Alert\"/>";
		xsd += "</xs:choice>";
		xsd += "</xs:sequence>";
		xsd += "</xs:complexType>";
		xsd += "</xs:element>";
		xsd += "<!-- Copy operation. -->";
		xsd += "<xs:element name=\"Copy\">";
		xsd += "<xs:complexType>";
		xsd += "<xs:sequence>";
		xsd += "<xs:element ref=\"CmdID\"/>";
		xsd += "<xs:element minOccurs=\"0\" ref=\"NoResp\"/>";
		xsd += "<xs:element minOccurs=\"0\" ref=\"Cred\"/>";
		xsd += "<xs:element minOccurs=\"0\" ref=\"Meta\"/>";
		xsd += "<xs:element maxOccurs=\"unbounded\" ref=\"Item\"/>";
		xsd += "</xs:sequence>";
		xsd += "</xs:complexType>";
		xsd += "</xs:element>";
		xsd += "<!-- Delete operation. -->";
		xsd += "<xs:element name=\"Delete\">";

		xsd += "<xs:complexType>";
		xsd += "  <xs:sequence>";
		xsd += "    <xs:element ref=\"CmdID\"/>";
		xsd += "    <xs:element minOccurs=\"0\" ref=\"NoResp\"/>";
		xsd += "     <xs:element minOccurs=\"0\" ref=\"Archive\"/>";
		xsd += "    <xs:element minOccurs=\"0\" ref=\"SftDel\"/>";
		xsd += "    <xs:element minOccurs=\"0\" ref=\"Cred\"/>";
		xsd += "    <xs:element minOccurs=\"0\" ref=\"Meta\"/>";
		xsd += "     <xs:element maxOccurs=\"unbounded\" ref=\"Item\"/>";
		xsd += "    </xs:sequence>";
		xsd += "  </xs:complexType>";
		xsd += " </xs:element>";
		xsd += " <!-- Exec operation -->";
		xsd += " <!-- Executable can either be referenced with Target element type -->";
		xsd += "<!-- or can be specified in the Data element type. -->";
		xsd += " <xs:element name=\"Exec\">";
		xsd += "  <xs:complexType>";
		xsd += " <xs:sequence>";
		xsd += "   <xs:element ref=\"CmdID\"/>";
		xsd += "    <xs:element minOccurs=\"0\" ref=\"NoResp\"/>";
		xsd += "    <xs:element minOccurs=\"0\" ref=\"Cred\"/>";
		xsd += "  <xs:element minOccurs=\"0\" ref=\"Meta\"/>";
		xsd += " <xs:element ref=\"Item\"/>";
		xsd += " </xs:sequence>";
		xsd += "  </xs:complexType>";
		xsd += "</xs:element>";
		xsd += "  <!-- Get operation. -->";
		xsd += "  <xs:element name=\"Get\">";
		xsd += "    <xs:complexType>";
		xsd += "      <xs:sequence>";
		xsd += "       <xs:element ref=\"CmdID\"/>";
		xsd += "       <xs:element minOccurs=\"0\" ref=\"NoResp\"/>";
		xsd += "       <xs:element minOccurs=\"0\" ref=\"Lang\"/>";
		xsd += "       <xs:element minOccurs=\"0\" ref=\"Cred\"/>";
		xsd += "        <xs:element minOccurs=\"0\" ref=\"Meta\"/>";
		xsd += "        <xs:element maxOccurs=\"unbounded\" ref=\"Item\"/>";
		xsd += "      </xs:sequence>";
		xsd += "    </xs:complexType>";
		xsd += "  </xs:element>";
		xsd += "  <!-- MAP operation. Create/Delete an item id map kept at the server. -->";
		xsd += "  <xs:element name=\"Map\">";
		xsd += "    <xs:complexType>";
		xsd += "      <xs:sequence>";
		xsd += "    <xs:element ref=\"CmdID\"/>";
		xsd += "     <xs:element ref=\"Target\"/>";
		xsd += "     <xs:element ref=\"Source\"/>";
		xsd += "     <xs:element minOccurs=\"0\" ref=\"Cred\"/>";
		xsd += "     <xs:element minOccurs=\"0\" ref=\"Meta\"/>";
		xsd += "     <xs:element maxOccurs=\"unbounded\" ref=\"MapItem\"/>";
		xsd += "   </xs:sequence>";
		xsd += "  </xs:complexType>";
		xsd += " </xs:element>";
		xsd += " <xs:element name=\"MapItem\">";
		xsd += "   <xs:complexType>";
		xsd += "     <xs:sequence>";
		xsd += "     <xs:element ref=\"Target\"/>";
		xsd += "     <xs:element ref=\"Source\"/>";
		xsd += "   </xs:sequence>";
		xsd += "  </xs:complexType>";
		xsd += "</xs:element>";
		xsd += "<!-- Put operation. -->";
		xsd += " <xs:element name=\"Put\">";
		xsd += "  <xs:complexType>";
		xsd += "    <xs:sequence>";
		xsd += "       <xs:element ref=\"CmdID\"/>";
		xsd += "     <xs:element minOccurs=\"0\" ref=\"NoResp\"/>";
		xsd += "     <xs:element minOccurs=\"0\" ref=\"Lang\"/>";
		xsd += "    <xs:element minOccurs=\"0\" ref=\"Cred\"/>";
		xsd += "    <xs:element minOccurs=\"0\" ref=\"Meta\"/>";
		xsd += "  <xs:element maxOccurs=\"unbounded\" ref=\"Item\"/>";
		xsd += "  </xs:sequence>";
		xsd += "  </xs:complexType>";
		xsd += " </xs:element>";
		xsd += " <!-- Replace operation. -->";
		xsd += "  <xs:element name=\"Replace\">";
		xsd += "    <xs:complexType>";
		xsd += "      <xs:sequence>";
		xsd += "        <xs:element ref=\"CmdID\"/>";
		xsd += "       <xs:element minOccurs=\"0\" ref=\"NoResp\"/>";
		xsd += "        <xs:element minOccurs=\"0\" ref=\"Cred\"/>";
		xsd += "        <xs:element minOccurs=\"0\" ref=\"Meta\"/>";
		xsd += "        <xs:element maxOccurs=\"unbounded\" ref=\"Item\"/>";
		xsd += "      </xs:sequence>";
		xsd += "    </xs:complexType>";
		xsd += "  </xs:element>";
		xsd += "  <!-- Results operation. -->";
		xsd += "  <xs:element name=\"Results\">";
		xsd += "    <xs:complexType>";
		xsd += "      <xs:sequence>";
		xsd += "        <xs:element ref=\"CmdID\"/>";
		xsd += "        <xs:element minOccurs=\"0\" ref=\"MsgRef\"/>";
		xsd += "        <xs:element ref=\"CmdRef\"/>";
		xsd += "       <xs:element minOccurs=\"0\" ref=\"Meta\"/>";
		xsd += "        <xs:element minOccurs=\"0\" ref=\"TargetRef\"/>";
		xsd += "        <xs:element minOccurs=\"0\" ref=\"SourceRef\"/>";
		xsd += "        <xs:element maxOccurs=\"unbounded\" ref=\"Item\"/>";
		xsd += "      </xs:sequence>";
		xsd += "    </xs:complexType>";
		xsd += "  </xs:element>";
		xsd += "  <!-- Search operation. -->";
		xsd += "  <xs:element name=\"Search\">";
		xsd += "    <xs:complexType>";
		xsd += "      <xs:sequence>";
		xsd += "       <xs:element ref=\"CmdID\"/>";
		xsd += "        <xs:element minOccurs=\"0\" ref=\"NoResp\"/>";
		xsd += "        <xs:element minOccurs=\"0\" ref=\"NoResults\"/>";
		xsd += "        <xs:element minOccurs=\"0\" ref=\"Cred\"/>";
		xsd += "        <xs:element minOccurs=\"0\" ref=\"Target\"/>";
		xsd += "        <xs:element maxOccurs=\"unbounded\" ref=\"Source\"/>";
		xsd += "        <xs:element minOccurs=\"0\" ref=\"Lang\"/>";
		xsd += "        <xs:element ref=\"Meta\"/>";
		xsd += "	        <xs:element ref=\"Data\"/>";
		xsd += "	      </xs:sequence>";
		xsd += "	    </xs:complexType>";
		xsd += "	  </xs:element>";
		xsd += "  <!-- Sequence operation. -->";
		xsd += "  <xs:element name=\"Sequence\">";
		xsd += "    <xs:complexType>";
		xsd += "      <xs:sequence>";
		xsd += "        <xs:element ref=\"CmdID\"/>";
		xsd += "        <xs:element minOccurs=\"0\" ref=\"NoResp\"/>";
		xsd += "        <xs:element minOccurs=\"0\" ref=\"Meta\"/>";
		xsd += "        <xs:choice maxOccurs=\"unbounded\">";
		xsd += "          <xs:element ref=\"Add\"/>";
		xsd += "	          <xs:element ref=\"Replace\"/>";
		xsd += "	          <xs:element ref=\"Delete\"/>";
		xsd += "          <xs:element ref=\"Copy\"/>";
		xsd += "     <xs:element ref=\"Atomic\"/>";
		xsd += "     <xs:element ref=\"Map\"/>";
		xsd += "    <xs:element ref=\"Sync\"/>";
		xsd += "   <xs:element ref=\"Get\"/>";
		xsd += "        <xs:element ref=\"Alert\"/>";
		xsd += "      <xs:element ref=\"Exec\"/>";
		xsd += "     </xs:choice>";
		xsd += "    </xs:sequence>";
		xsd += "    </xs:complexType>";
		xsd += "  </xs:element>";
		xsd += "  <!-- Status operation. -->";
		xsd += "  <xs:element name=\"Status\">";
		xsd += "    <xs:complexType>";
		xsd += "  <xs:sequence>";
		xsd += "     <xs:element ref=\"CmdID\"/>";
		xsd += "     <xs:element ref=\"MsgRef\"/>";
		xsd += "     <xs:element ref=\"CmdRef\"/>";
		xsd += "      <xs:element ref=\"Cmd\"/>";
		xsd += "       <xs:element minOccurs=\"0\" maxOccurs=\"unbounded\" ref=\"TargetRef\"/>";
		xsd += "       <xs:element minOccurs=\"0\" maxOccurs=\"unbounded\" ref=\"SourceRef\"/>";
		xsd += "       <xs:element minOccurs=\"0\" ref=\"Cred\"/>";
		xsd += "        <xs:element minOccurs=\"0\" ref=\"Chal\"/>";
		xsd += "        <xs:element ref=\"Data\"/>";
		xsd += "        <xs:element minOccurs=\"0\" maxOccurs=\"unbounded\" ref=\"Item\"/>";
		xsd += "      </xs:sequence>";
		xsd += "    </xs:complexType>";
		xsd += "  </xs:element>";
		xsd += "  <!-- Synchronize Operation. -->";
		xsd += "  <xs:element name=\"Sync\">";
		xsd += "    <xs:complexType>";
		xsd += "      <xs:sequence>";
		xsd += "        <xs:element ref=\"CmdID\"/>";
		xsd += "    <xs:element minOccurs=\"0\" ref=\"NoResp\"/>";
		xsd += "     <xs:element minOccurs=\"0\" ref=\"Cred\"/>";
		xsd += "     <xs:element minOccurs=\"0\" ref=\"Target\"/>";
		xsd += "     <xs:element minOccurs=\"0\" ref=\"Source\"/>";
		xsd += "     <xs:element minOccurs=\"0\" ref=\"Meta\"/>";
		xsd += "      <xs:element minOccurs=\"0\" ref=\"NumberOfChanges\"/>";
		xsd += "       <xs:choice minOccurs=\"0\" maxOccurs=\"unbounded\">";
		xsd += "         <xs:element ref=\"Add\"/>";
		xsd += "          <xs:element ref=\"Atomic\"/>";
		xsd += "         <xs:element ref=\"Copy\"/>";
		xsd += "          <xs:element ref=\"Delete\"/>";
		xsd += "          <xs:element ref=\"Replace\"/>";
		xsd += "          <xs:element ref=\"Sequence\"/>";
		xsd += "        </xs:choice>";
		xsd += "      </xs:sequence>";
		xsd += "    </xs:complexType>";
		xsd += "  </xs:element>";
		xsd += "  <xs:element name=\"Routing\">";
		xsd += "  <xs:complexType>";
		xsd += "     <xs:sequence>";
		xsd += "       <xs:element name=\"Lang\" minOccurs=\"0\" type=\"xs:string\" />";
		xsd += "       <xs:element name=\"Device\" minOccurs=\"0\" type=\"xs:string\" />";
		xsd += "        <xs:element minOccurs=\"0\" ref=\"Ver\"/>";
		xsd += "        <xs:element minOccurs=\"0\" ref=\"Apps\"/>";
		xsd += "      </xs:sequence>";
		xsd += "    </xs:complexType>";
		xsd += "	  </xs:element>";
		xsd += " <xs:element name=\"Ver\">";
		xsd += "  <xs:complexType>";
		xsd += "   <xs:sequence>";
		xsd += "		<xs:element name=\"SupportVersion\" minOccurs=\"0\" type=\"xs:string\" />";
		xsd += "		<xs:element name=\"CompatibleVersion\" minOccurs=\"0\" type=\"xs:string\" />";
		xsd += " 		<xs:element name=\"URL\" minOccurs=\"0\" type=\"xs:string\" />";
		xsd += "    	<xs:element name=\"Client\" minOccurs=\"0\" type=\"xs:string\" />";
		xsd += "     </xs:sequence>";
		xsd += "   </xs:complexType>";
		xsd += "  </xs:element>";
		xsd += "  <xs:element name=\"Apps\">";
		xsd += "    <xs:complexType>";
		xsd += "      <xs:sequence>";
		xsd += "        <xs:element maxOccurs=\"unbounded\" ref=\"URI\" />";
		xsd += "      </xs:sequence>";
		xsd += "    </xs:complexType>";
		xsd += "  </xs:element>";
		xsd += "  <xs:element  name=\"URI\">";
		xsd += " <xs:complexType>";
		xsd += " <xs:simpleContent>";
		xsd += "    <xs:extension base=\"xs:string\">";
		xsd += "       <xs:attribute name=\"type\" type=\"xs:string\" use=\"required\" />";
		xsd += "     </xs:extension>";
		xsd += "   </xs:simpleContent>";
		xsd += "   </xs:complexType>";
		xsd += " </xs:element>";
		xsd += " <xs:element name=\"Key\">";
		xsd += "  <xs:complexType>";
		xsd += "     <xs:sequence>";
		xsd += "     <xs:element ref=\"CmdID\" />";
		xsd += "      <xs:element name=\"Data\" type=\"xs:string\" />";
		xsd += "    </xs:sequence>";
		xsd += "   </xs:complexType>";
		xsd += "  </xs:element>";
		xsd += " <xs:element name=\"ReceiveEmail\">";
		xsd += "   <xs:complexType>";
		xsd += "     <xs:sequence>";
		xsd += "      <xs:element ref=\"CmdID\"  />";
		xsd += "     </xs:sequence>";
		xsd += "    </xs:complexType>";
		xsd += "  </xs:element>";
		xsd += "<xs:element name=\"SendEmail\">";
		xsd += " <xs:complexType>";
		xsd += "   <xs:sequence>";
		xsd += "       <xs:element name=\"CmdID\" />";
		xsd += "        <xs:element name=\"Data\" type=\"xs:string\" />";
		xsd += "        <xs:element ref=\"Email\"  />";
		xsd += "	      </xs:sequence>";
		xsd += "	    </xs:complexType>";
		xsd += " </xs:element>";
		xsd += " <xs:element name=\"Email\">";
		xsd += "    <xs:complexType>";
		xsd += "      <xs:simpleContent>";
		xsd += "        <xs:extension base=\"xs:string\">";
		xsd += "          <xs:attribute name=\"RefId\" type=\"xs:string\" use=\"required\" />";
		xsd += "	        </xs:extension>";
		xsd += "	      </xs:simpleContent>";
		xsd += "	    </xs:complexType>";
		xsd += "	  </xs:element>";
		xsd += "	</xs:schema>";
		xsd += "	<!-- End of DTD Definition -->";

		return xsd;
	}
	
	public static String getMetaSchema() {
		String xsd = "";
		xsd += "<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema' xmlns=\"http://protocol.columboid.com/syncml/metainfo\" elementFormDefault=\"qualified\" targetNamespace=\"http://protocol.columboid.com/syncml/metainfo\">";
		
		xsd += "<xs:element name='Anchor'>";
		xsd += "<xs:complexType>";
		xsd += " <xs:sequence>";
		xsd += "   <xs:element ref='Last' minOccurs='0'/>";
		xsd += "  <xs:element ref='Next'/>";
		xsd += " </xs:sequence>";
		xsd += " </xs:complexType>";
		xsd += "</xs:element>";
		
		xsd += "<xs:element name='EMI'>";
		xsd += "<xs:complexType mixed='true'>";
		xsd += "</xs:complexType>";
		xsd += "</xs:element>";
		
		xsd += "<xs:element name='Format'>";
		xsd += "<xs:complexType mixed='true'>";
		xsd += "</xs:complexType>";
		xsd += "</xs:element>";
		
		xsd += " <xs:element name='FreeID'>";
		xsd += "<xs:complexType mixed='true'>";
		xsd += "</xs:complexType>";
		xsd += "</xs:element>";
		
		xsd += " <xs:element name='FreeMem'>";
		xsd += " <xs:complexType mixed='true'>";
		xsd += " </xs:complexType>";
		xsd += "</xs:element>";
		
		xsd += "<xs:element name='Last'>";
		xsd += "<xs:complexType mixed='true'>";
		xsd += " </xs:complexType>";
		xsd += "</xs:element>";
		
		xsd += "<xs:element name='Mark'>";
		xsd += "<xs:complexType mixed='true'>";
		xsd += " </xs:complexType>";
		xsd += " </xs:element>";
		
		xsd += "<xs:element name='MaxMsgSize'>";
		xsd += " <xs:complexType mixed='true'>";
		xsd += " </xs:complexType>";
		xsd += " </xs:element>";
		
		xsd += "<xs:element name='MaxObjSize'>";
		xsd += "  <xs:complexType mixed='true'>";
		xsd += " </xs:complexType>";
		xsd += "</xs:element>";
		
		xsd += "<xs:element name='Mem'>";
		xsd += "<xs:complexType>";
		xsd += "<xs:sequence>";
		xsd += " <xs:element ref='SharedMem' minOccurs='0'/>";
		xsd += " <xs:element ref='FreeMem'/>";
		xsd += "<xs:element ref='FreeID'/>";
		xsd += "</xs:sequence>";
		xsd += "</xs:complexType>";
		xsd += " </xs:element>";
		
		xsd += " <xs:element name='MetInf'>";
		xsd += "<xs:complexType>";
		
		xsd += "<xs:sequence>";
		xsd += " <xs:element ref='Format' minOccurs='0'/>";
		xsd += " <xs:element ref='Type' minOccurs='0'/>";
		xsd += "<xs:element ref='Mark' minOccurs='0'/>";
		xsd += " <xs:element ref='Size' minOccurs='0'/>";
		xsd += "<xs:element ref='Anchor' minOccurs='0'/>";
		xsd += "<xs:element ref='Version' minOccurs='0'/>";
		xsd += "<xs:element ref='NextNonce' minOccurs='0'/>";
		xsd += "<xs:element ref='MaxMsgSize' minOccurs='0'/>";
		xsd += "<xs:element ref='MaxObjSize' minOccurs='0'/>";
		xsd += "<xs:element ref='EMI' minOccurs='0' maxOccurs='unbounded'/>";
		xsd += "<xs:element ref='Mem' minOccurs='0'/>";
		xsd += "</xs:sequence>";
		xsd += " </xs:complexType>";
		xsd += "</xs:element>";
		
		xsd += " <xs:element name='Next'>";
		xsd += "<xs:complexType mixed='true'>";
		xsd += " </xs:complexType>";
		xsd += "</xs:element>";
		
		xsd += "<xs:element name='NextNonce'>";
		xsd += "<xs:complexType mixed='true'>";
		xsd += "</xs:complexType>";
		xsd += "</xs:element>";
		
		xsd += "<xs:element name='SharedMem'>";
		xsd += " <xs:complexType/>";
		xsd += "</xs:element>";
		
		xsd += " <xs:element name='Size'>";
		xsd += "<xs:complexType mixed='true'>";
		xsd += " </xs:complexType>";
		xsd += "</xs:element>";
		
		xsd += "<xs:element name='Type'>";
		xsd += "<xs:complexType mixed='true'>";
		xsd += " </xs:complexType>";
		xsd += "</xs:element>";
		
		xsd += "<xs:element name='Version'>";
		xsd += "<xs:complexType mixed='true'>";
		xsd += " </xs:complexType>";
		xsd += "</xs:element>";
		xsd += "</xs:schema>";
		return xsd;
		
	}
}
